package com.rover.system.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.rover.system.dao.BaseDao;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.hibernate.type.StandardBasicTypes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;




@Repository("baseDao")
public class BaseDaoImpl  implements BaseDao {

	@Autowired
	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	private Session getSession() {
		return this.sessionFactory.getCurrentSession();
	}


    @Override
    public <T> void save(T o) {
        getSession().save(o);
        getSession().flush();
    }

    @Override
    public <T> void delete(T o) {
        getSession().delete(o);
        getSession().flush();
    }

    @Override
    public  void delete(Class c, Serializable id) {
        this.getSession().delete(get(c, id));
        getSession().flush();
    }
    @Override
    public  void delete(Class c,Collection<Integer> list){
        for (Serializable obj : list) {
            delete( c,obj );
        }
    }
    /**
     * 删除全部的实体
     *
     * @param <T>
     *
     * @param entitys
     */
    @Override
    public <T> void deleteAllEntitie(Collection<T> entitys) {
        for (Object entity : entitys) {
            getSession().delete(entity);
            getSession().flush();
        }
    }
    @Override
    public <T> void update(T o) {
        getSession().update(o);
        getSession().flush();
        getSession().clear();
    }

    @Override
    public <T> void saveOrUpdate(T o) {

        getSession().saveOrUpdate(o);
        getSession().flush();
        getSession().clear();
    }

    @Override
    public <T> T get(Class c, Serializable id) {
       T t=  (T) getSession().get(c, id);
        return t;
    }


    /**
     * 批量保存数据
     * @param <T>
     * @param entitys 要持久化的临时实体对象集合
     */
    @Override
    public <T> void batchSave(List<T> entitys) {
        for (int i=0; i<entitys.size();i++) {
            getSession().save(entitys.get(i));
            if (i % 20 == 0) {
                //20个对象后才清理缓存，写入数据库
                getSession().flush();
                getSession().clear();
            }

        }
    }

    @Override
    public <T> T get(String hql, Map<String, Object> params) {
        Query q = this.getSession().createQuery(hql);
        setQueryParams(q,params);
        List<T> l = q.list();
        getSession().clear();
        if (l != null && l.size() > 0) {
            return l.get(0);
        }
        return null;
    }

    @Override
    public <T> List<T> findHql(String hql, Map<String, Object> params) {
        Query q = this.getSession().createQuery(hql);
        //缓存
        q.setCacheable(true);
        setQueryParams(q,params);
        List<T>  l= q.list();
        return l;
    }

    /*
     * 设置查询说需要的参数
     * */
    private void setQueryParams(Query q, Map<String, Object> params){
    	 if (params != null && !params.isEmpty()) {
             for (String key : params.keySet()) {
                 if( params.get(key).getClass().getName().equals("java.util.ArrayList") ){
                         q.setParameterList(key,(List)params.get(key));
                 }
                   else  {
                 q.setParameter(key, params.get(key));
                 }
             }
         }
    }

    @Override
    public <T> List<T> findPageHql(String hql, int page, int rows) {
        Query q = this.getSession().createQuery(hql);
        return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
    }

    @Override
    public <T> List<T> findPageHql(String hql, Map<String, Object> params, int page, int rows) {
        Query q = this.getSession().createQuery(hql);

        setQueryParams(q,params);
        return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
    }



    @Override
	public Object uniqueResultHql(String hql, Map<String, Object> params) {
		Query q = this.getSession().createQuery(hql);
		 setQueryParams(q,params);
		return  q.uniqueResult();
	}



	@Override
	public int executeHql(String hql, Map<String, Object> params) {
		Query q = this.getSession().createQuery(hql);
		 setQueryParams(q,params);
		return q.executeUpdate();
	}




	@Override
	public Long countHql(String hql, Map<String, Object> params) {
		return (Long)this.uniqueResultHql(hql, params);
	}

             /*以下是sql语句*/

    @Override
    public <T> List<T> findSQL(String sql, Map<String, Object> params) {
        Query query = this.getSession().createSQLQuery(sql);
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                query.setParameter(key, params.get(key));
            }
        }
        return query.list();
    }


    @Override
    public Object uniqueResultSQL(String sql, Map<String, Object> params) {
        Query query = this.getSession().createSQLQuery(sql);
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                query.setParameter(key, params.get(key));
            }
        }
        return query.uniqueResult();
    }

    @Override
    public Long countSQL(String sql, Map<String, Object> params) {
      return      (Long) uniqueResultSQL(sql,params);
    }

    @Override
    public int executeSQL(String sql, Map<String, Object> params) {
        Query query = this.getSession().createSQLQuery(sql);
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                query.setParameter(key, params.get(key));
            }
        }
        return query.executeUpdate();
    }

	
    /*
     * 返回指定实体
     * */
    @Override
    public <T> List<T> findSQLPersistence(Class c,String sql, Map<String, Object> params) {
        Query query = this.getSession().createSQLQuery(sql).addEntity(c);;
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                query.setParameter(key, params.get(key));
            }
        }
        return query.list();
    }


   /*
    * 非实体类
    * */
    @Override
    public <T> List<T>  findSQLNonPersistence(Class c,String sql, Map<String, Object> params) {
        SQLQuery query =null;
        query = (SQLQuery) this.getSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(c));
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            if(field.getType().equals(String.class))
                query.addScalar(field.getName(), StandardBasicTypes.STRING);
            else if(field.getType().equals(Integer.class))
                query.addScalar(field.getName(),StandardBasicTypes.INTEGER);
            else if(field.getType().equals(BigDecimal.class))
                query.addScalar(field.getName(),StandardBasicTypes.BIG_DECIMAL);
            else if(field.getType().equals(Long.class))
                query.addScalar(field.getName(),StandardBasicTypes.LONG);
            else if(field.getType().equals(Date.class))
                query.addScalar(field.getName(),StandardBasicTypes.DATE);
            else if(field.getType().equals(Float.class))
                query.addScalar(field.getName(),StandardBasicTypes.FLOAT);
            else if(field.getType().equals(Short.class))
                query.addScalar(field.getName(),StandardBasicTypes.SHORT);
            else if(field.getType().equals(Double.class))
                query.addScalar(field.getName(),StandardBasicTypes.DOUBLE);
            else if(field.getType().equals(Byte.class))
                query.addScalar(field.getName(),StandardBasicTypes.BYTE);
            else if(field.getType().equals(Boolean.class))
                query.addScalar(field.getName(),StandardBasicTypes.BOOLEAN);
        }
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                query.setParameter(key, params.get(key));
            }
        }
        return query.list();
    }






}